import 'dart:math';

import 'package:flutter_utils/flutter_utils.dart';

typedef RetryAction<T> = Future<T> Function(int retryCount);
typedef RetryIf = bool Function(dynamic);
typedef RetryInterval = Duration Function(int);

/// 重试异步任务，最多重试[maxRetry]次，
/// [action]要执行的异步任务，传入当前重试次数
/// [retryIf]传入捕获到的异常，返回是否重试；默认都会重试
/// [interval] 传入当前重试次数，可以指定每次重试休眠时间，默认是400*2^(retryCount)毫秒
Future<T> retryAsync<T>(
    {required RetryAction<T> action,
    int maxRetry = 1,
    RetryIf? retryIf,
    RetryInterval? interval,
    bool enableLog = false}) async {
  for (var i = 0; i <= maxRetry; i++) {
    try {
      if (enableLog) {
        LogUtil.logD('Run async start-----retryCount=$i');
      }
      return await action(i);
    } catch (e) {
      final isRetry = i + 1 <= maxRetry && (retryIf?.call(e) ?? true);
      if (isRetry) {
        await Future.delayed(interval?.call(i) ??
            Duration(milliseconds: (400 * pow(2, i)).round()));
      } else {
        rethrow;
      }
    }
  }
  throw 'retryAsync failed after retry $maxRetry times';
}
